/*
 * Copyright (c) 2014 laidian. All Rights Reserved.
 * @author yaoyuming
 * @date  2020-01-11 10:01
 */
package com.yao.common.util;

import cn.hutool.core.collection.CollectionUtil;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * @author yaoyuming
 * @date 2020/01/11 10:01
 */
public class SQLUtils {

    protected final static Logger logger = LoggerFactory.getLogger(SQLUtils.class);

    public static <T> boolean execute(SQLOperation<T> sqlOperation, T t) {
        try {
            int result = sqlOperation.execute(t);
            return result == 1;
        } catch (Exception e) {
            logger.error(e.getMessage());
            return false;
        }
    }

    public static <T, R, M> M get(T t, SQLQuery<T, R> query, ModelToDTOConverter<R, M> converter) {
        return get(t, query, converter, e -> e);
    }

    public static <T, R, M> M get(T t, SQLQuery<T, R> query, ModelToDTOConverter<R, M> converter, DTOMapper<M> mapper) {
        R r = query.execute(t);
        if (r != null) {
            return mapper.map(converter.convert(r));
        }
        return null;
    }

    public static <T extends BasePageQuery, M, R> List<R> getList(T t, SQLPageQuery<T, M> pageQuery, ModelToDTOConverter<M, R> modelToDTO) {
        return getList(t, pageQuery, modelToDTO, e -> e);
    }
    public static <T extends BasePageQuery, M, R> List<R> getList(T t, SQLListQuery<T, M> listQuery, ModelToDTOConverter<M, R> modelToDTO) {
        return getList(t, listQuery, modelToDTO, e -> e);
    }

    /***
     * 查询列表(无分页)
     * @param t 查询参数，继承自BasePageQuery
     * @param listQuery  DAO查询器
     * @param modelToDTO model转换成dto方法
     * @param mapper dto自转方法
     * @param <T>  查询参数类型
     * @param <M>  model类类型
     * @param <R>  dto类类型
     * @return
     */
    public static <T extends BasePageQuery, M, R> List<R> getList(T t, SQLListQuery<T, M> listQuery, ModelToDTOConverter<M, R> modelToDTO, DTOMapper<R> mapper) {
        List<M> modelList = listQuery.getList(t);
        List<R> dtoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(modelList)) {
            modelList.stream().map(e -> modelToDTO.convert(e)).map(mapper::map).forEach(dtoList::add);
        }
        return dtoList;
    }



    /***
     * 查询列表
     * @param t 查询参数，继承自BasePageQuery
     * @param pageQuery  DAO查询器
     * @param modelToDTO model转换成dto方法
     * @param mapper dto自转方法
     * @param <T>  查询参数类型
     * @param <M>  model类类型
     * @param <R>  dto类类型
     * @return
     */
    public static <T extends BasePageQuery, M, R> List<R> getList(T t, SQLPageQuery<T, M> pageQuery,
                                                                  ModelToDTOConverter<M, R> modelToDTO, DTOMapper<R> mapper) {
        List<M> modelList = pageQuery.getPage(t, PageUtils.genRowBounds(t));
        List<R> dtoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(modelList)) {
            modelList.stream().map(e -> modelToDTO.convert(e)).map(mapper::map).forEach(dtoList::add);
        }
        return dtoList;
    }

    /*public static <T extends BasePageQuery, M, R> PageResponseDTO<R> getPage(T t, SQLPageQuery<T, M> pageQuery, ModelToDTOConverter<M, R> modelToDTO) {
        return getPage(t, pageQuery, modelToDTO, e -> e);
    }

    public static <T extends BasePageQuery, M, R> PageResponseDTO<R> getPage(T t, SQLPageQuery<T, M> pageQuery, ModelToDTOConverter<M, R> modelToDTO, DTOMapper<R> mapper) {
        PageResponseDTO<R> pageResponseDTO = new PageResponseDTO<>();
        pageResponseDTO.setRows(getList(t, pageQuery, modelToDTO, mapper));
        PageUtils.fillPageResponse(pageResponseDTO, t, RecordCountHelper.getCount());
        return pageResponseDTO;
    }

    public static <T extends BasePageQuery, M, R> PageResponseDTO<R> getPage(T t, String countSQL, SQLPageCountQuery<T, M> pageQuery, ModelToDTOConverter<M, R> modelToDTO, DTOMapper<R> mapper) {
        PageResponseDTO<R> pageResponseDTO = new PageResponseDTO<>();
        List<M> modelList = pageQuery.getPage(t, PageUtils.genCountBounds(t, countSQL));
        List<R> dtoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(modelList)) {
            modelList.stream().map(e -> modelToDTO.convert(e)).map(mapper::map).forEach(dtoList::add);
        }
        pageResponseDTO.setRows(dtoList);
        PageUtils.fillPageResponse(pageResponseDTO, t, RecordCountHelper.getCount());
        return pageResponseDTO;
    }

    public static <T extends LoanBasePageQuery, M, R> PageResponseDTO<R> getPage(T t, PageQuery<T, M> pageQuery,
                                                                                 CountQuery<T, M> countQuery, ModelToDTOConverter<M, R> modelToDTO, DTOMapper<R> mapper) {
        PageResponseDTO<R> pageResponseDTO = new PageResponseDTO<>();
        t.genPageParameter();
        List<M> modelList = pageQuery.getPage(t);
        List<R> dtoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(modelList)) {
            modelList.stream().map(e -> modelToDTO.convert(e)).map(mapper::map).forEach(dtoList::add);
        }
        pageResponseDTO.setRows(dtoList);
        PageUtils.fillPageResponse(pageResponseDTO, t, countQuery.getCount(t));
        return pageResponseDTO;
    }*/

    @FunctionalInterface
    public interface SQLOperation<T> {
        int execute(T t);
    }

    @FunctionalInterface
    public interface SQLQuery<T, R> {
        R execute(T t);
    }

    @FunctionalInterface
    public interface PageQuery<T extends BasePageQuery, R> {
        List<R> getPage(T t);
    }

    @FunctionalInterface
    public interface CountQuery<T extends BasePageQuery, R> {
        int getCount(T t);
    }

    @FunctionalInterface
    public interface SQLPageQuery<T extends BasePageQuery, R> {
        List<R> getPage(T t, RowBounds rowBounds);
    }

/*    @FunctionalInterface
    public interface SQLPageCountQuery<T extends BasePageQuery, R> {
        List<R> getPage(T t, CountBounds countBounds);
    }*/

    @FunctionalInterface
    public interface SQLListQuery<T extends BasePageQuery, R> {
        List<R> getList(T t);
    }

    @FunctionalInterface
    public interface ModelToDTOConverter<T, R> {
        R convert(T t);
    }

    @FunctionalInterface
    public interface DTOMapper<T> {
        T map(T t);
    }
}
